#pragma once

#include "Thread.h"
#include "SimpleSocket.h"
#include "SocketEvent.h"

namespace RoomFW {

/// Generic Socket Server.  Accepts and manages client connections.
/// Derived classes must implement virtual functions to be useful.
///
///   @author Andrew Sage
class SocketServer : public virtual EventThread
{
public:

	/// ctor
	SocketServer(void);

	/// dtor
	virtual ~SocketServer(void);

	/// Starts the object which runs in its own thread.
	///     @param port - TCP/IP port to listen on.
	///     @param address - TCP/IP address to listen on.
	///     @param timeout - Passed to Thread::start().
	///   @return Success.
	virtual bool start(int port, const char* address, uint32_t timeout = INFINITE);

	/// Connect to a remote server
	///     @param port - TCP/IP port to connect to.
	///     @param address - TCP/IP address to connect to.
	///   @return Socket.
	virtual SimpleSocket::SocketPtr connect(int port, const char* address);

protected:

	/// Called when a new client is connected.  Derived classes may override.
	///     @param client - New client.
	///   @return Success.  False will exit the thread.
	virtual bool handleConnect(SimpleSocket::SocketPtr /*client*/) {return true;}

	/// Called when a client disconnects.  Derived classes may override.
	///     @param client - Client that disconnected.
	///   @return Success.  False will exit the thread.
	virtual bool handleDisconnect(SimpleSocket::SocketPtr /*client*/) {return true;}

	/// Called to handle a client message.  Derived classes may override.
	///     @param client - Client message received from.
	///     @param message - message received.
	///   @return Success.  False will exit the thread.
	virtual bool handleMessage(SimpleSocket::SocketPtr /*client*/, const std::string& /*message*/) {return true;}

	///
	/// Thread overrides.  See Thread for documentation.  Derived classes probably shouldn't override.
	///
	virtual bool initializeObject(void);
	virtual bool initializeThread(void);
	virtual bool waitEvent(void);
	virtual bool handleEvent(void);
	virtual void signalStop(void);
	virtual void finalize(void);

private:

	/// Stop event.
	SimpleEvent stopEvent_;

	/// TCP/IP port to listen on.
	int port_;

	/// TCP/IP address to listen on.
	std::string address_;

	/// Listener socket;
	SocketEventSP listener_;

	/// Client sockets
	typedef std::vector<SocketEventSP> SocketEventArray;
	SocketEventArray client_;

	/// Thread safe initiation of connection to remote servers.
	typedef std::queue<SocketEventSP> SocketEventQueue;
	SocketEventQueue connectQueue_;
	SimpleCriticalSection connectQueueSynch_;
	SimpleEvent connectQueueEvent_;

	/// Not designed to be copied.
	SocketServer(const SocketServer&);
	SocketServer& operator =(const SocketServer&);
};

}
